const utils = require("../utils");
const csstree = require("css-tree");
const prettier = require("prettier");
const zhtmdata = require('./zhtmdata');
const zcssdata = require('./zcssdata');

function zcssTranspile(cssFile, zcssFileContent) {
    const cssFileContent = prettier.format(transpile(zcssFileContent), { parser: "css" });
    utils.writeFileContents(cssFile, cssFileContent);
}

const atruleMap = zcssdata.atruleMap;
const pseudoElementMap = zcssdata.pseudoElementMap;
const pseudoClassMap = zcssdata.pseudoClassMap;
const propertyMap = zcssdata.propertyMap;
const identMap = zcssdata.identMap;
const dimensionMap = zcssdata.dimensionMap;
const shorthandMap = zcssdata.shorthandMap;

function astHandler(ast) {
    csstree.walk(ast, function (node, item, list) {
        try {
        let tagMap = zhtmdata.tagMap;
        switch (node.type) {
            case "TypeSelector":
                if (node.name in tagMap) {
                    let zName = node.name
                    if (typeof tagMap[zName] === 'string') {
                        node.name = tagMap[zName];
                    } else {
                        node.name = tagMap[zName]['eName'];
                    }
                    node.zname = zName; // 用于处理属性选择器
                }
                break;

            case "AttributeSelector": //中文属性已保留, 这里的处理已成多余?
                let globalAttrMap = zhtmdata.globalAttrMap;
                let eventMap = zhtmdata.eventMap;
                let attrZName = node.name.name;
                let typeName = item.prev.data.zname;
                let attrEName;

                if (attrZName.startsWith('数据-')) {
                    node.name.name = 'data-' + attrZName.slice(3)
                } else
                    if (typeName in tagMap) {
                        attrEName = tagMap[typeName]["attrs"][attrZName] || globalAttrMap[attrZName] || eventMap[attrZName];
                    } else { // 前面是非标准元素或通用选择器(*)
                        attrEName = globalAttrMap[attrZName] || eventMap[attrZName];
                    }

                if (attrEName) {
                    if (typeof attrEName === "string") {
                        node.name.name = attrEName;
                    } else {
                        node.name.name = attrEName["eName"];

                        let attrZValue = node.value.value;
                        if (attrZValue) {
                            node.value.value = attrEName["attrValues"][eval(attrZValue)] || attrZValue; // 注意, 这里要用 eval 脱引号
                        }
                    }
                }
                break;

            case "Atrule":
                // console.log(node.prelude);
                if (node.name in atruleMap) {
                    node.name = atruleMap[node.name];
                    if (node.name === 'media') { // @媒体 处理; 是否要考虑 @media 后面有中文的翻译?
                        let zValue = node.prelude.value;
                        let mediaQueryMap = zcssdata.mediaQueryMap;
                        let eValue = zValue.replace(/[\u4e00-\u9fa5-]+/g, function(word) {
                            return mediaQueryMap[word] || word;
                        });
                        node.prelude.value = eValue;
                    }
                }
                break;

            case "PseudoElementSelector":
                if (node.name in pseudoElementMap) {
                    node.name = pseudoElementMap[node.name];
                }
                break;
            
            case "PseudoClassSelector":
                if (node.name in pseudoClassMap) {
                    node.name = pseudoClassMap[node.name];
                }
                break;

            case "Declaration":
                let zProperty = node.property;
                let destMap = (zProperty in shorthandMap) ? shorthandMap: ((zProperty in propertyMap)? propertyMap: undefined);
                if (destMap) {
                    if (typeof destMap[zProperty] === 'object') {
                        node.property = destMap[zProperty]['eName'];
                    } else {
                        node.property = destMap[zProperty];
                    }
                }

                let valueChildren = node.value.children;
                valueChildren.forEach(zChild => {                    
                    // console.log(zChild);
                    if (zChild.type === 'Identifier' || zChild.type === 'Function') {
                        let zChildName = zChild.name;
                        if (destMap && typeof destMap[zProperty] === 'object') {
                            zChild.name = destMap[zProperty]['values'][zChildName] || identMap[zChildName] || zChildName;
                            if (zChild.children && typeof zChild.name === 'object') { // 处理 Function 参数
                                funObjMap = zChild.name;
                                zChild.name = funObjMap['eName'];
                                zChild.children.forEach(paraChild => {
                                    if (paraChild.type === 'Identifier' || zChild.type === 'Function') {
                                        paraChild.name = funObjMap['paras'][paraChild.name] || paraChild.name;
                                    }
                                });
                            }
                        } else {
                            zChild.name = identMap[zChildName] || zChildName;
                        }
                    }
                }); 
                break;

            case "Identifier":
                if (node.name.match(/[\u4e00-\u9fa5]+/)) {
                    if (node.name in identMap) {                        
                        node.name = identMap[node.name];
                    } else 
                    if (node.name.startsWith('数据-')) {
                        node.name = 'data-' + node.name.slice(3);
                    }
                }
                break;
            
            case "Dimension":
                if (node.unit in dimensionMap) {
                    node.unit = dimensionMap[node.unit];
                }
                break;
        }
        }
        catch(err) {
            console.log(err);
        }
    });
}

function transpile(source) {
    // parse CSS to AST
    var ast = csstree.parse(source);

    // traverse AST and modify it
    astHandler(ast);

    // generate CSS from AST
    return csstree.generate(ast);
    // return prettier.format(csstree.generate(ast), { parser: "css" });
}

module.exports = {
    zcssTranspile,
    astHandler,
    transpile
};
